/* 
自定义Promise
*/
((window) => {
  // 定义状态值常量
  const PENDING = 'pending';
  const FULFILLED = 'fulfilled';
  const REJECTED = 'rejected';

  /**
   * 构造函数
   * @param  excutor 执行器函数
   */

  /* 
    promise对象内部要存储哪些信息?
      1. 状态: pending/fulfilled/rejected  ==> state
      2. 结果数据: undefined/value/reason  ==> data
      3. 保存待处理回调的数组: [{resolved () {}, rejected () {}}, {resolved () {}, rejected () {}}] => callbacks
   
      在构造函数中, 会立即同步调用执行器函数, 并传入resolve和reject 两个函数

      resolve函数
        参数: value
        作用: 将promise的状态改为resolved, 将value保存到data
      reject函数
        参数: reason
        作用: 将promise的状态改为rejected, 将reason保存到data
    */
  function Promise(excutor) {
    /* 初始化3个属性 */
    // 1. 状态: pending/fulfilled/rejected  ==> state
    this.state = PENDING;
    // 2. 结果数据: undefined/value/reason  ==> data
    this.data = undefined;
    // 3. 保存待处理回调的数组: [{resolved () {}, rejected () {}}, {resolved () {}, rejected () {}}] => callbacks
    this.callbacks = [];

    const self = this;

    /* 
    resolve函数
        参数: value
        作用: 将promise的状态改为resolved, 将value保存到data
    */
    function resolve(value) {
      // 只有当前状态为pendding, 才向下处理
      if (self.state!==PENDING) return

      // 改状态为成功的
      self.state = FULFILLED
      // 保存数据
      self.data = value
      // 异步执行callbacks中所有成功的回调
      // 我们没办法直接向微队列中添加回调 => 只能用宏队列了 setTimeout
      setTimeout(() => {
        self.callbacks.forEach(callbackObj => callbackObj.resolved(value))
      }, 0)
      
    }

    /* 
  reject函数
      参数: reason
      作用: 将promise的状态改为rejected, 将reason保存到data
  */
    function reject(reason) {
      // 只有当前状态为pendding, 才向下处理
      if (self.state!==PENDING) return

      // 改状态为失败的
      self.state = REJECTED
      // 保存数据
      self.data = reason
      // 异步执行callbacks中所有成功的回调
      // 我们没办法直接向微队列中添加回调 => 只能用宏队列了 setTimeout
      setTimeout(() => {
        self.callbacks.forEach(callbackObj => callbackObj.rejected(reason))
      }, 0)
    }

    // 捕获执行器抛出的错误
    try {
      /*  在构造函数中, 会立即同步调用执行器函数, 并传入resolve和reject 两个函数 */
      excutor(resolve, reject);
    } catch (error) {
      // 将当前promise变为rejected, reason为error
      reject(error)
    }
    
  }

  /**
   * 指定成功和失败的回调, 并返回一个新的promise
   * @param {*} onResolved 成功的回调 => 用于得到成功的value
   * @param {*} onRejected 失败的回调 => 用于得到失败的reason
   */
  /* 
   then返回的promise的结果由什么决定
		简单表达: 由then指定的回调执行的结果决定
      返回promise  ==> 得到并改为它的状态
      返回非promise  ==> 变为成功状态
      抛出错误   ==> try---catch  => 变为失败状态
  */
  Promise.prototype.then = function (onResolved, onRejected) {
    console.log('then()')
    const self = this

    // 返回一个新的promise
    return new Promise((resolve, reject) => {
      if (self.state===FULFILLED) { // 如果当前promise是成功的, 异步执行成功的回调
        setTimeout(() => {
          try {
            const result = onResolved(self.data)
            if (result instanceof Promise) { // 情况1: 返回promise  ==> 得到并改为它的状态
              result.then(
                value => resolve(value),
                reason => reject(reason)
              )
            } else { // 情况2: 返回非promise  ==> 变为成功状态
              resolve(result)
            }
          } catch (error) { // 情况3: 抛出错误   ==> try---catch  => 变为失败状态
            reject(error)
          }
          

        }, 0)
      } else if (self.state===REJECTED) { // 如果当前promise是失败的, 异步执行失败的回调
        setTimeout(() => {
          try {
            const result = onRejected(self.data)
            if (result instanceof Promise) { // 情况1: 返回promise  ==> 得到并改为它的状态
              result.then(
                value => resolve(value),
                reason => reject(reason)
              )
            } else { // 情况2: 返回非promise  ==> 变为成功状态
              resolve(result)
            }
          } catch (error) { // 情况3: 抛出错误   ==> try---catch  => 变为失败状态
            reject(error)
          }
          
        }, 0)
      } else { // 如果当前promise是pending, 保存成功和失败的回调

        this.callbacks.push({
          // 问题: 不会根据成功/失败回调执行的结果个改变返回的promise的状态
          // resolve: onResolved,

          resolved: (value) => {
            console.log('my onResolved')
            try {
              const result = onResolved(self.data)
              if (result instanceof Promise) { // 情况1: 返回promise  ==> 得到并改为它的状态
                result.then(
                  value => resolve(value),
                  reason => reject(reason)
                )
              } else { // 情况2: 返回非promise  ==> 变为成功状态
                resolve(result)
              }
            } catch (error) { // 情况3: 抛出错误   ==> try---catch  => 变为失败状态
              reject(error)
            }
          },
          rejected: (reason) => {
            console.log('my onRejected')
            
            try {
              const result = onRejected(reason)
              if (result instanceof Promise) {
                result.then(
                  value => {resolve(value)},
                  reason => reject(reason)
                )
              } else {
                resolve(result)
              }
            } catch (error) {
              reject(error)
            }
          }
        })
      }
    })

    
  };

  /**
   * 指定失败的回调, 并返回一个新的promise
   * @param {*} onRejected 失败的回调 => 用于得到失败的reason
   */
  Promise.prototype.catch = function (onRejected) {};

  /**
   *  返回一个成功的promise, value为指定的value
   * @param {*} value
   */
  Promise.resolve = function (value) {};

  /**
   *  返回一个失败的promise, reason为指定的reason
   * @param {*} reason
   */
  Promise.reject = function (reason) {};

  /**
   * 返回一个promise, 如果promises都成功, 它才成功, 成功的value为所有value组成的数组, 只要有一个失败, 那它就失败了
   * @param {*} promises
   */
  Promise.all = function (promises) {};

  /**
   * 返回一个promise, 由第一个完成的promie来决定它的结果
   * @param {*} promises
   */
  Promise.race = function (promises) {};

  /**
   * 返回一个promise, 当所有promise都完成时它就成功, value值为所有promise的value或reason组成的数组
   * @param {*} promises
   */
  Promise.allSettled = function (promises) {};

  window.Promise = Promise;
})(window);
